/**
 * PHOSIDE: PHosphorylation Site IDentification Engine.
 * Copyright 2009 Digital Biology Lab, University of Missouri.
 * This library is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 3 of the License, or (at your option) any later
 * version. <p/> This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the License for more
 * details.
 */

package phoside.ui;

import java.io.File;

import java.util.ArrayList;

import javax.swing.JFileChooser;
import javax.swing.JOptionPane;

import phoside.PhosideInit;
import phoside.PhosphoProteins;
import phoside.PhosphoProteinsImpl;
import phoside.Proteins;

import phoside.data.nr.ProteinClusterBlastClust;
import phoside.data.nr.ProteinNR100Builder;
import phoside.data.nr.ProteinNRBuilderImpl;

import phoside.io.xml.PhosideXmlProteinsReader;
import phoside.io.xml.PhosideXmlProteinsWriter;
import phoside.io.xml.PhosphoProteinFieldValueFormatter;

import phoside.ui.task.ProteinsNRBuildTask;
import phoside.ui.task.ProteinsReadTask;
import phoside.ui.task.ProteinsWriteTask;
import phoside.ui.task.TaskUtil;

import phoside.util.FileExtensionsFilter;
import phoside.util.FilePathParser;

/**
 *
 * @author gjj
 */
public class ProteinsNRBuildDialog extends javax.swing.JDialog {

    /** Creates new form Fasta2XmlDialog */
    public ProteinsNRBuildDialog(java.awt.Frame parent, boolean modal) {
        super(parent, modal);
        initComponents();
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {
        java.awt.GridBagConstraints gridBagConstraints;

        javax.swing.ButtonGroup singleBothButtonGroup = new javax.swing.ButtonGroup();
        javax.swing.JPanel originalPanel = new javax.swing.JPanel();
        javax.swing.JPanel originalFilePanel = new javax.swing.JPanel();
        originalFileTextField = new javax.swing.JTextField();
        javax.swing.JButton originalFileButton = new javax.swing.JButton();
        javax.swing.JPanel targetPanel = new javax.swing.JPanel();
        javax.swing.JPanel targetFilePanel = new javax.swing.JPanel();
        targetFileTextField = new javax.swing.JTextField();
        javax.swing.JButton targetFileButton = new javax.swing.JButton();
        javax.swing.JPanel OKPanel = new javax.swing.JPanel();
        OKBtn = new javax.swing.JButton();
        javax.swing.JButton cancelBtn = new javax.swing.JButton();
        javax.swing.JPanel paramPanel = new javax.swing.JPanel();
        javax.swing.JPanel simCovPanel = new javax.swing.JPanel();
        javax.swing.JLabel simLabel = new javax.swing.JLabel();
        simTextField = new javax.swing.JTextField();
        javax.swing.JLabel simDescLabel = new javax.swing.JLabel();
        javax.swing.JLabel covLabel = new javax.swing.JLabel();
        covTextField = new javax.swing.JTextField();
        javax.swing.JLabel covDescLabel = new javax.swing.JLabel();
        javax.swing.JPanel bothOrSinglePanel = new javax.swing.JPanel();
        bothRadioButton = new javax.swing.JRadioButton();
        singleRadioButton = new javax.swing.JRadioButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        setTitle("Non-redundant builder");
        getContentPane().setLayout(new java.awt.GridBagLayout());

        originalPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Redundant PHOSIDE XML file"));
        originalPanel.setLayout(new java.awt.GridBagLayout());

        originalFilePanel.setLayout(new java.awt.GridBagLayout());

        originalFileTextField.setToolTipText("Please select a FASTA training file");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        originalFilePanel.add(originalFileTextField, gridBagConstraints);

        originalFileButton.setText("Open");
        originalFileButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                originalFileButtonActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_END;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        originalFilePanel.add(originalFileButton, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
        gridBagConstraints.weightx = 1.0;
        originalPanel.add(originalFilePanel, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        getContentPane().add(originalPanel, gridBagConstraints);

        targetPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Save Non-Redundant PHOSIDE XML file to"));
        targetPanel.setMinimumSize(new java.awt.Dimension(400, 63));
        targetPanel.setPreferredSize(new java.awt.Dimension(500, 63));
        targetPanel.setLayout(new java.awt.GridBagLayout());

        targetFilePanel.setLayout(new java.awt.GridBagLayout());

        targetFileTextField.setToolTipText("Please select a FASTA training file");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        targetFilePanel.add(targetFileTextField, gridBagConstraints);

        targetFileButton.setText("Open");
        targetFileButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                targetFileButtonActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_END;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        targetFilePanel.add(targetFileButton, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
        gridBagConstraints.weightx = 1.0;
        targetPanel.add(targetFilePanel, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        getContentPane().add(targetPanel, gridBagConstraints);

        OKBtn.setText("   OK   ");
        OKBtn.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                OKBtnActionPerformed(evt);
            }
        });
        OKPanel.add(OKBtn);

        cancelBtn.setText("Cancel");
        cancelBtn.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                cancelBtnActionPerformed(evt);
            }
        });
        OKPanel.add(cancelBtn);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 4;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_END;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        getContentPane().add(OKPanel, gridBagConstraints);

        paramPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Parameters"));
        paramPanel.setLayout(new java.awt.GridBagLayout());

        simCovPanel.setLayout(new java.awt.GridBagLayout());

        simLabel.setText("Similarity threshold:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_END;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        simCovPanel.add(simLabel, gridBagConstraints);

        simTextField.setText("50");
        simTextField.setPreferredSize(new java.awt.Dimension(60, 19));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        simCovPanel.add(simTextField, gridBagConstraints);

        simDescLabel.setForeground(new java.awt.Color(153, 153, 153));
        simDescLabel.setText("Integer between 3 and 100");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        simCovPanel.add(simDescLabel, gridBagConstraints);

        covLabel.setText("Coverage threshold:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_END;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        simCovPanel.add(covLabel, gridBagConstraints);

        covTextField.setText("0.9");
        covTextField.setPreferredSize(new java.awt.Dimension(60, 19));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        simCovPanel.add(covTextField, gridBagConstraints);

        covDescLabel.setForeground(new java.awt.Color(153, 153, 153));
        covDescLabel.setText("Number between 0.0 and 1.0");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        simCovPanel.add(covDescLabel, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.weightx = 1.0;
        paramPanel.add(simCovPanel, gridBagConstraints);

        bothOrSinglePanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Require coverage on both or only one sequence of a pair?"));
        bothOrSinglePanel.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT));

        singleBothButtonGroup.add(bothRadioButton);
        bothRadioButton.setText("Both");
        bothOrSinglePanel.add(bothRadioButton);

        singleBothButtonGroup.add(singleRadioButton);
        singleRadioButton.setSelected(true);
        singleRadioButton.setText("Single");
        bothOrSinglePanel.add(singleRadioButton);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.weightx = 1.0;
        paramPanel.add(bothOrSinglePanel, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        getContentPane().add(paramPanel, gridBagConstraints);

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void originalFileButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_originalFileButtonActionPerformed
        JFileChooser fc = new JFileChooser(PhosideInit.defaultPath);
        ArrayList<String> exts = new ArrayList<String>(1);
        String ext = "xml";
        exts.add(ext);
        fc.setFileFilter(new FileExtensionsFilter(exts,"PHOSIDE XML file (.xml)"));
        //fc.setAcceptAllFileFilterUsed(true);
        fc.setDialogTitle("Select a PHOSIDE XML file...");
        int returnVal = fc.showOpenDialog(this);
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            File file = fc.getSelectedFile();
            PhosideInit.defaultPath = file.getParent();

            String filePath = PhosideInit.defaultPath + File.separator + file.getName();
            originalFileTextField.setText(filePath);

            String fileName = FilePathParser.getName(filePath);
            targetFileTextField.setText(PhosideInit.defaultPath+File.separator+fileName+"-nr.xml");
        }
}//GEN-LAST:event_originalFileButtonActionPerformed

    private void targetFileButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_targetFileButtonActionPerformed
        JFileChooser fc;
        String defFile = targetFileTextField.getText();
        if (defFile.length()>0) {
            fc = new JFileChooser(FilePathParser.getDir(defFile));
        } else {
            fc = new JFileChooser(PhosideInit.defaultPath);
        }

        String ext = "xml";
        fc.setSelectedFile(new File(defFile));
        ArrayList<String> exts = new ArrayList<String>(1);
        exts.add(ext);
        fc.setFileFilter(new FileExtensionsFilter(exts,"XML file (.xml)"));
        //fc.setAcceptAllFileFilterUsed(true);
        fc.setDialogTitle("Save to...");
        int returnVal = fc.showSaveDialog(this);
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            File file = fc.getSelectedFile();
            PhosideInit.defaultPath = file.getParent();

            String filePath = PhosideInit.defaultPath + File.separator + file.getName();
            targetFileTextField.setText(filePath);
        }
    }//GEN-LAST:event_targetFileButtonActionPerformed

    private void OKBtnActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_OKBtnActionPerformed
        String dirOriginal = originalFileTextField.getText();
        if (dirOriginal.length()==0) {
            JOptionPane.showMessageDialog(this, "Error: specify a file containing the protein sequences.");
            return;
        }

        String dirXml = targetFileTextField.getText();
        if (dirXml.length()==0) {
            JOptionPane.showMessageDialog(this, "Error: specify the xml file to save.");
            return;
        }

        if (phoside.util.IOUtil.fileExist(dirXml)) {
            int ret = JOptionPane.showConfirmDialog(this, "Are you sure to replace the existing xml file?",
                    null, JOptionPane.YES_NO_OPTION);
            if (ret==JOptionPane.NO_OPTION) {
                return;
            }
        }

        String strSim = simTextField.getText();
        if (strSim.length()==0) {
            JOptionPane.showMessageDialog(this, "Error: no similarity threshold specified.");
            return;
        }

        int sim;
        try {
            sim = Integer.parseInt(strSim);
        } catch (NumberFormatException e) {
            e.printStackTrace();
            JOptionPane.showMessageDialog(this, "Error: similarity threshold can only be an integer number between 3 and 100.");
            return;
        }

        if (sim<3 || sim>100) {
            JOptionPane.showMessageDialog(this, "Error: similarity threshold can only be an integer number between 3 and 100.");
            return;
        }

        String strCov = covTextField.getText();
        if (strSim.length()==0) {
            JOptionPane.showMessageDialog(this, "Error: no coverage threshold specified.");
            return;
        }

        double cov;
        try {
            cov = Double.parseDouble(strCov);
        } catch (NumberFormatException e) {
            e.printStackTrace();
            JOptionPane.showMessageDialog(this, "Error: coverage threshold can only be an number between 0 and 0.1.");
            return;
        }

        if (cov<0 || cov>1) {
            JOptionPane.showMessageDialog(this, "Error: coverage threshold can only be an number between 0 and 0.1.");
            return;
        }

        //Reading phospho data
        PhosphoProteins phosphoData = new PhosphoProteinsImpl();
        PhosideXmlProteinsReader phosphoReader =
                new PhosideXmlProteinsReader(dirOriginal, phosphoData,
                    new PhosphoProteinFieldValueFormatter());

        ProteinsReadTask phosphoReadTask = new ProteinsReadTask(phosphoReader);
        TaskUtil.execute(phosphoReadTask);
        if (!phosphoReadTask.success()) {
            JOptionPane.showMessageDialog(this, "Failed to read the original file");
            return;
        }

        boolean both = bothRadioButton.isSelected();

        // Build nr100
        ProteinNR100Builder nr100Builder = new ProteinNR100Builder();
        ProteinsNRBuildTask nr100Task = new ProteinsNRBuildTask(nr100Builder, phosphoData);
        TaskUtil.execute(nr100Task);
        if (!nr100Task.success()) {
            JOptionPane.showMessageDialog(this, "Failed to build the nr db.");
            return;
        }
        Proteins nrProteins = nr100Task.getNRProteins();

        // Build nr
        if (sim<100 || cov<1 || !both) { // if not exactly same
            String blosumDir = PhosideInit.matrixDir.getAbsolutePath();
            ProteinClusterBlastClust cluster = new ProteinClusterBlastClust(
                    blosumDir, sim, cov, both);
            ProteinNRBuilderImpl nrBuilder = new ProteinNRBuilderImpl(cluster);

            ProteinsNRBuildTask nrTask = new ProteinsNRBuildTask(nrBuilder, nrProteins);
            TaskUtil.execute(nrTask);
            if (!nrTask.success()) {
                JOptionPane.showMessageDialog(this, "Failed to build the nr db.");
                return;
            }
            nrProteins = nrTask.getNRProteins();
        }

        //Write to xml file
        PhosideXmlProteinsWriter writer = new PhosideXmlProteinsWriter(dirXml,
                new PhosphoProteinFieldValueFormatter());
        ProteinsWriteTask xmlWriteTask = new ProteinsWriteTask(nrProteins, writer);
        TaskUtil.execute(xmlWriteTask);
        if (!xmlWriteTask.success()) {
            JOptionPane.showMessageDialog(this, "Failed to write the xml file");
            return;
        }

        JOptionPane.showMessageDialog(this, "Done.");
        
        this.setVisible(false);
        this.dispose();
}//GEN-LAST:event_OKBtnActionPerformed

    private void cancelBtnActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelBtnActionPerformed
        setVisible(false);
        dispose();
}//GEN-LAST:event_cancelBtnActionPerformed


    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton OKBtn;
    private javax.swing.JRadioButton bothRadioButton;
    private javax.swing.JTextField covTextField;
    private javax.swing.JTextField originalFileTextField;
    private javax.swing.JTextField simTextField;
    private javax.swing.JRadioButton singleRadioButton;
    private javax.swing.JTextField targetFileTextField;
    // End of variables declaration//GEN-END:variables

}
